/* Copyright 2007 Gearbox Software - http://www.gearboxsoft.com
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
     http:www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.*/
namespace GearBlog.Web.Models
{
	using System.Security.Cryptography;
	using System.Security.Principal;
	using System.Text;
	using Castle.ActiveRecord;
	using Castle.ActiveRecord.Validators;
	using Castle.Components.Validator;
	using Iesi.Collections.Generic;
	using NHibernate.Expression;

	/// <summary>
    /// Summary description for User
    /// </summary>
    [ActiveRecord(Table="AppUsers")]
    public class User:ExtendedActiveRecordBase<User>, IPrincipal, IIdentity
    {
        private string _userName;
        private string _fullName;
        private string _email;
        private byte[] _passwordHash;
        private bool _isEnabled;
    	private bool _notifyNewPost;
    	private bool _autoSubscribeComments;
        private ISet<Role> _roles;
        
        private string _password;
        private string _confirmPassword;

        public User()
        {
            _roles = new HashedSet<Role>();
            _isEnabled = true;
        	_notifyNewPost = false;
        	_autoSubscribeComments = false;
        }
		[Property(Length = 30), ValidateNonEmpty, ValidateCompositeIsUnique(new string[] {"UserName"},"User Name" )]
		public string UserName
		{
			get { return _userName; }
			set { _userName = value; }
		}

        [Property(Length=100),ValidateNonEmpty]
        public string FullName
        {
            get { return _fullName; }
            set { _fullName = value; }
        }

        [Property(Length=100),ValidateNonEmpty]
        public string Email
        {
            get { return _email; }
            set { _email = value; }
        }
        [Property(NotNull=true)]
        public byte[] PasswordHash
        {
            get { return _passwordHash; }
            set { _passwordHash = value; }
        }
        [Property(NotNull=true)]
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set { _isEnabled = value; }
        }
		[ValidateNonEmpty("Password cannot be empty",RunWhen=RunWhen.Insert|RunWhen.Custom)]
        public string Password
        {
            get { return _password; }
            set
            {
            	_password = value;
				SetPasswordHash();
            }
        }

		[ValidateSameAs("Password", RunWhen = RunWhen.Insert | RunWhen.Custom)]
        public string ConfirmPassword
        {
            get { return _confirmPassword; }
            set { _confirmPassword = value; }
        }

        public void SetPasswordHash()
        {
            _passwordHash = GetHash(_password);
        }

        public bool IsPasswordCorrect(string password)
        {
            byte[] trialHash = GetHash(password);
            if (trialHash.Length != _passwordHash.Length) return false;
            for (int i = 0; i < trialHash.Length; i++)
            {
                if (trialHash[i] != _passwordHash[i]) return false;
            }
            return true;
        }
        private byte[] GetHash(string value)
        {
            SHA1 sha1 = SHA1.Create();
            return sha1.ComputeHash(UnicodeEncoding.UTF8.GetBytes(value));
        }

        [HasAndBelongsToMany(ColumnKey="UserID",ColumnRef="RoleID",Table="UserRole", Inverse=false)]
        public ISet<Role> Roles
        {
            get { return _roles; }
            set { _roles = value; }
        }

		//Receives Notifications if new Post has been submitted
		[Property(NotNull=true)]
    	public bool NotifyNewPost
    	{
    		get { return _notifyNewPost; }
    		set { _notifyNewPost = value; }
    	}

		//Auto Subscribe to comments when a new post is originated/comment is posted under a particular post
		[Property(NotNull = true)]
    	public bool AutoSubscribeComments
    	{
    		get { return _autoSubscribeComments; }
    		set { _autoSubscribeComments = value; }
    	}

    	#region IIdentity Members

        public string AuthenticationType
        {
            get { return ""; }
        }

        public bool IsAuthenticated
        {
            get { return true; }
        }

        public string Name
        {
            get { return _userName; }
        }
        public bool IsInRole(string roleName)
        {
            foreach (Role role in _roles)
            {
                if (string.Compare(role.Name, roleName, true) == 0) return true;
            }
            return false;
        }

        #endregion

        public static User FindByUserName(string userName)
        {
            return FindOne(new EqExpression("UserName", userName));
        }

        public static User FindByKey(string key)
        {
            return FindOne(new EqExpression("Key", key));
        }



		#region IPrincipal Members

		public IIdentity Identity
		{
			get { return this; }
		}

		#endregion

		public static User FindByEmail(string email)
		{
			return FindOne(new EqExpression("Email", email));
		}
    }
}
